package com.highspeed.bdk.gateway;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;

public class Util {
    /* Convert byte[] to hex string.这里我们可以将byte转换成int，然后利用Integer.toHexString(int)来转换成16进制字符串。
     * @param src byte[] data
     * @return hex string
     */
    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

    /**
     * Convert hex string to byte[]
     *
     * @param hexString the hex string
     * @return byte[]
     */
    public static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }

    /**
     * Convert char to byte
     *
     * @param c char
     * @return byte
     */
    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

    public static void printHexString(byte[] b) {
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            System.out.print(hex.toUpperCase());
        }

    }

    public static String bytes2HexString(byte[] b) {
        String ret = "";
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            ret += hex.toUpperCase();
        }
        return ret;
    }

    public static void createFile(String path, String fileName) {
//path表示你所创建文件的路径
        File f = new File(path);
        if (!f.exists()) {
            f.mkdirs();
        }
// fileName表示你创建的文件名；为txt类型；
        File file = new File(f, fileName);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
// TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    public static byte[] getContent(String filePath) throws IOException {
        File file = new File(filePath);
        long fileSize = file.length();
        if (fileSize > Integer.MAX_VALUE) {
            System.out.println("file too big...");
            return null;
        }
        FileInputStream fi = new FileInputStream(file);
        byte[] buffer = new byte[(int) fileSize];
        int offset = 0;
        int numRead = 0;
        while (offset < buffer.length
                && (numRead = fi.read(buffer, offset, buffer.length - offset)) >= 0) {
            offset += numRead;
        }
        // 确保所有数据均被读取
        if (offset != buffer.length) {
            throw new IOException("Could not completely read file "
                    + file.getName());
        }
        fi.close();
        return buffer;
    }

    /**
     * 获取流
     *
     * @param filePath
     * @return
     * @throws IOException
     */
    public static FileInputStream getStream(String filePath) throws IOException {
        File file = new File(filePath);
        long fileSize = file.length();
        if (fileSize > Integer.MAX_VALUE) {
            System.out.println("file too big...");
            return null;
        }
        FileInputStream fi = new FileInputStream(file);
        return fi;
    }

    /**
     * 转换short为byte
     *
     * @param b
     * @param s     需要转换的short
     * @param index
     */
    public static void putShort(byte b[], short s, int index) {
        b[index + 1] = (byte) (s >> 0);
        b[index + 0] = (byte) (s >> 8);
    }

    /**
     * 通过byte数组取到short
     *
     * @param b
     * @param index 第几位开始取
     * @return
     */
    public static short getShort(byte[] b, int index) {
        return (short) (((b[index + 1] & 0xff) | b[index + 0] << 8));
    }

    /**
     * 获取short的无符号数
     *
     * @param b
     * @param index
     * @return
     */
    public static int getUnsignedShort(byte[] b, int index) {
        return (((b[index + 1] & 0xff) | b[index + 0] << 8)) & 0x0FFFF;
    }

    /**
     * 转换int为byte数组
     *
     * @param bb
     * @param x
     * @param index
     */
    public static void putInt(byte[] bb, int x, int index) {
        bb[index + 3] = (byte) (x >> 0);
        bb[index + 2] = (byte) (x >> 8);
        bb[index + 1] = (byte) (x >> 16);
        bb[index + 0] = (byte) (x >> 24);
    }

    /**
     * 通过byte数组取到int
     *
     * @param bb
     * @param index 第几位开始
     * @return
     */
    public static int getInt(byte[] bb, int index) {
        return ((bb[index + 3] & 0xff) << 0) | ((bb[index + 2] & 0xff) << 8) | ((bb[index + 1] & 0xff) << 16) | ((bb[index + 0] & 0xff) << 24);
    }

    /**
     * 获取int的无符号数
     *
     * @param bb
     * @param index
     * @return
     */
    public static long getUnsignedInt(byte[] bb, int index) {
        return ((bb[index + 3] << 0) | (bb[index + 2] << 8) | (bb[index + 1] << 16) | (bb[index + 0] << 24)) & 0x0FFFFFFFFL;
    }

    /**
     * 转换long型为byte数组
     *
     * @param bb
     * @param x
     * @param index
     */
    public static void putLong(byte[] bb, long x, int index) {
        bb[index + 7] = (byte) (x >> 0);
        bb[index + 6] = (byte) (x >> 8);
        bb[index + 5] = (byte) (x >> 16);
        bb[index + 4] = (byte) (x >> 24);
        bb[index + 3] = (byte) (x >> 32);
        bb[index + 2] = (byte) (x >> 40);
        bb[index + 1] = (byte) (x >> 48);
        bb[index + 0] = (byte) (x >> 56);
    }

    /**
     * 通过byte数组取到long
     *
     * @param bb
     * @param index
     * @return
     */
    public static long getLong(byte[] bb, int index) {
        return ((((long) bb[index + 7] & 0xff) << 0)
                | (((long) bb[index + 6] & 0xff) << 8)
                | (((long) bb[index + 5] & 0xff) << 16)
                | (((long) bb[index + 4] & 0xff) << 24)
                | (((long) bb[index + 3] & 0xff) << 32)
                | (((long) bb[index + 2] & 0xff) << 40)
                | (((long) bb[index + 1] & 0xff) << 48) | (((long) bb[index + 0] & 0xff) << 56));
    }

    /**
     * 字符到字节转换
     *
     * @param ch
     * @return
     */
    public static void putChar(byte[] bb, char ch, int index) {
        int temp = (int) ch;
        // byte[] b = new byte[2];
        for (int i = 0; i < 2; i++) {
            bb[index + i] = new Integer(temp & 0xff).byteValue(); // 将最高位保存在最低位
            temp = temp >> 8; // 向右移8位
        }
    }

    public static void putByte(byte[] bb, byte b, int index) {
        bb[index + 0] = b;
    }


    /**
     * 字节到字符转换
     *
     * @param b
     * @return
     */
    public static char getChar(byte[] b, int index) {
        int s = 0;
        if (b[index + 1] > 0)
            s += b[index + 1];
        else
            s += 256 + b[index + 0];
        s *= 256;
        if (b[index + 0] > 0)
            s += b[index + 1];
        else
            s += 256 + b[index + 0];
        char ch = (char) s;
        return ch;
    }

    /**
     * float转换byte
     *
     * @param bb
     * @param x
     * @param index
     */
    public static void putFloat(byte[] bb, float x, int index) {
        // byte[] b = new byte[4];
        int l = Float.floatToIntBits(x);
        for (int i = 0; i < 4; i++) {
            bb[index + i] = new Integer(l).byteValue();
            l = l >> 8;
        }
    }

    /**
     * 通过byte数组取得float
     *
     * @param bb
     * @param index
     * @return
     */
    public static float getFloat(byte[] b, int index) {
        int l;
        l = b[index + 0];
        l &= 0xff;
        l |= ((long) b[index + 1] << 8);
        l &= 0xffff;
        l |= ((long) b[index + 2] << 16);
        l &= 0xffffff;
        l |= ((long) b[index + 3] << 24);
        return Float.intBitsToFloat(l);
    }

    /**
     * double转换byte
     *
     * @param bb
     * @param x
     * @param index
     */
    public static void putDouble(byte[] bb, double x, int index) {
        // byte[] b = new byte[8];
        long l = Double.doubleToLongBits(x);
        for (int i = 0; i < 4; i++) {
            bb[index + i] = new Long(l).byteValue();
            l = l >> 8;
        }
    }

    /**
     * 通过byte数组取得float
     *
     * @param bb
     * @param index
     * @return
     */
    public static double getDouble(byte[] b, int index) {
        long l;
        l = b[0];
        l &= 0xff;
        l |= ((long) b[1] << 8);
        l &= 0xffff;
        l |= ((long) b[2] << 16);
        l &= 0xffffff;
        l |= ((long) b[3] << 24);
        l &= 0xffffffffl;
        l |= ((long) b[4] << 32);
        l &= 0xffffffffffl;
        l |= ((long) b[5] << 40);
        l &= 0xffffffffffffl;
        l |= ((long) b[6] << 48);
        l &= 0xffffffffffffffl;
        l |= ((long) b[7] << 56);
        return Double.longBitsToDouble(l);
    }

    /**
     * 将一个单字节的byte转换成32位的int
     *
     * @param b byte
     * @return convert result
     */
    public static int unsignedByteToInt(byte b) {
        return (int) b & 0xFF;
    }

    /**
     * 将一个单字节的Byte转换成十六进制的数
     *
     * @param b byte
     * @return convert result
     */
    public static String byteToHex(byte b) {
        int i = b & 0xFF;
        return Integer.toHexString(i);
    }

    /**
     * 将一个4byte的数组转换成32位的int
     *
     * @param buf            bytes buffer
     * @param byte[]中开始转换的位置
     * @return convert result
     */
    public static long unsigned4BytesToInt(byte[] buf, int pos) {
        int firstByte = 0;
        int secondByte = 0;
        int thirdByte = 0;
        int fourthByte = 0;
        int index = pos;
        firstByte = (0x000000FF & ((int) buf[index]));
        secondByte = (0x000000FF & ((int) buf[index + 1]));
        thirdByte = (0x000000FF & ((int) buf[index + 2]));
        fourthByte = (0x000000FF & ((int) buf[index + 3]));
        index = index + 4;
        return ((long) (firstByte << 24 | secondByte << 16 | thirdByte << 8 | fourthByte)) & 0xFFFFFFFFL;
    }

    /**
     * 将16位的short转换成byte数组
     *
     * @param s short
     * @return byte[] 长度为2
     */
    public static byte[] shortToByteArray(short s) {
        byte[] targets = new byte[2];
        for (int i = 0; i < 2; i++) {
            int offset = (targets.length - 1 - i) * 8;
            targets[i] = (byte) ((s >>> offset) & 0xff);
        }
        return targets;
    }

    /**
     * 将32位整数转换成长度为4的byte数组
     *
     * @param s int
     * @return byte[]
     */
    public static byte[] intToByteArray(int s) {
        byte[] targets = new byte[2];
        for (int i = 0; i < 4; i++) {
            int offset = (targets.length - 1 - i) * 8;
            targets[i] = (byte) ((s >>> offset) & 0xff);
        }
        return targets;
    }

    /**
     * long to byte[]
     *
     * @param s long
     * @return byte[]
     */
    public static byte[] longToByteArray(long s) {
        byte[] targets = new byte[2];
        for (int i = 0; i < 8; i++) {
            int offset = (targets.length - 1 - i) * 8;
            targets[i] = (byte) ((s >>> offset) & 0xff);
        }
        return targets;
    }

    /**
     * 32位int转byte[]
     */
    public static byte[] int2byte(int res) {
        byte[] targets = new byte[4];
        targets[0] = (byte) (res & 0xff);// 最低位
        targets[1] = (byte) ((res >> 8) & 0xff);// 次低位
        targets[2] = (byte) ((res >> 16) & 0xff);// 次高位
        targets[3] = (byte) (res >>> 24);// 最高位,无符号右移。
        return targets;
    }

    /**
     * 将长度为2的byte数组转换为16位int
     *
     * @param res byte[]
     * @return int
     */
    public static int byte2int(byte[] res) {
        // res = InversionByte(res);
        // 一个byte数据左移24位变成0x??000000，再右移8位变成0x00??0000
        int targets = (res[0] & 0xff) | ((res[1] << 8) & 0xff00); // | 表示安位或
        return targets;
    }

    /**
     * 将byte转换为一个长度为8的byte数组，数组每个值代表bit
     */
    public static byte[] getBooleanArray(byte b) {
        byte[] array = new byte[8];
        for (int i = 7; i >= 0; i--) {
            array[i] = (byte) (b & 1);
            b = (byte) (b >> 1);
        }
        return array;
    }

    /**
     * 把byte转为字符串的bit
     */
    public static String byteToBit(byte b) {
        return ""
                + (byte) ((b >> 7) & 0x1) + (byte) ((b >> 6) & 0x1)
                + (byte) ((b >> 5) & 0x1) + (byte) ((b >> 4) & 0x1)
                + (byte) ((b >> 3) & 0x1) + (byte) ((b >> 2) & 0x1)
                + (byte) ((b >> 1) & 0x1) + (byte) ((b >> 0) & 0x1);
    }

    /**
     * 获取byte
     *
     * @param bytes
     * @param index
     * @return
     */
    public static byte getByte(byte[] bytes, int index) {
        return (byte) (bytes[index + 0] & 0xff >> 0);
    }

    /**
     * 获取byte的无符号数
     *
     * @param bytes
     * @param index
     * @return
     */
    public static int getUnsignedByte(byte[] bytes, int index) {
        return (bytes[index + 0] & 0xff >> 0) & 0x0FFF;
    }

    /**
     * 将字符串转化为bcd码，每2位成一个字节
     *
     * @param bytes  字节数组
     * @param offset 字节便宜量
     * @param str    字符串
     * @return
     */
    public static int stringToBCD(byte[] bytes, int offset, String str) {
        if (str == null || "".equals(str.trim())) {
            return 0;
        }
        int len = str.length();
        int returnOffset = 0;
        if (len % 2 == 0) {
            int s = 0;
            for (int i = 0; i < len; i++) {

                //每一个字符占位四个字节，两个字符就是一个字节
                Integer num = Integer.parseInt(str.charAt(i) + "");
                for (int j = 0; j < 4; j++) {
                    if (i % 2 == 0) {

                        //字符下标为单数的时候，作为字节的高四位
                        s += (int) (((num >> j) & 0x1) * Math.pow(2, 4 + j));
                    } else {

                        //字符下标为单数的时候，作为字节的低四位
                        s += (int) (((num >> j) & 0x1) * Math.pow(2, j));
                    }
                }
                //已经处理完两个字符，可以放入byte数组里面
                if (i % 2 == 1) {
                    bytes[offset++] = (byte) s;
                    returnOffset++;
                    s = 0;
                }
            }
        }
        return returnOffset;
    }

    public static String byteToString(byte[] bytes, int offset) {
        byte b = bytes[offset];
        String str = "" + (int) (((b >> 7) & 0x1) * Math.pow(2, 3) + (((b >> 6) & 0x1) * Math.pow(2, 2)) + (((b >> 5) & 0x1) * Math.pow(2, 1)) + (((b >> 4) & 0x1) * Math.pow(2, 0)));
        int low = (int) (((b >> 3) & 0x1) * Math.pow(2, 3) + (((b >> 2) & 0x1) * Math.pow(2, 2)) + (((b >> 1) & 0x1) * Math.pow(2, 1)) + (((b >> 0) & 0x1) * Math.pow(2, 0)));
        str += low;
        return str;
    }

    public static byte[] getSubBytes(byte[] bytes, int offset, int len) {
        byte[] bs = new byte[len];
        for (int i = 0; i < len; i++) {
            bs[i] = bytes[i + offset];
        }
        return bs;
    }

    public static String subBytesToString(byte[] bytes, int offset, int len) {
        byte[] sub = getSubBytes(bytes, offset, len);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < sub.length; i++) {
            sb.append((char) (sub[i]));
        }
        String appName = sb.toString().trim();
        return appName;
    }

    public static void main(String[] args) {
        byte b = 0x35; // 0011 0101
        // 输出 [0, 0, 1, 1, 0, 1, 0, 1]
        System.out.println(Arrays.toString(getBooleanArray(b)));
        // 输出 00110101
        System.out.println(byteToBit(b));
        // JDK自带的方法，会忽略前面的 0
        System.out.println(Integer.toBinaryString(0x35));
    }

}
